package service

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"prometheus-sd-nacos/model"
	"prometheus-sd-nacos/service/respmodel"
	"strings"
	"sync"
)

// GenJobConfs gen job conf file for prometheus
func GenJobConfs(conf model.Config) error {
	services := conf.Services
	var wg sync.WaitGroup
	for _, srv := range services {
		wg.Add(1)
		go genJobConf(&wg, conf, srv)
	}
	return nil
}

func genJobConf(wg *sync.WaitGroup, conf model.Config, srv model.Service) {
	defer wg.Done()
	instances := getInstance(conf, srv)
	if instances == nil || len(instances) == 0 {
		log.Printf("seveice %s has no instances", srv)
		return
	}
	writeJobFile(srv, instances)
}

func getInstance(conf model.Config, srv model.Service) []respmodel.Instance {
	url := fmt.Sprintf("%s/v1/ns/instance/list?namespaceId=%s&groupName=%s&serviceName=%s", conf.NacosHost,
		conf.NamespaceID, conf.Group, srv.Name)
	log.Println("requst url:", url)

	resp, err := http.Get(url)
	if err != nil {
		log.Println("error: ", err)
		return nil
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		log.Printf("error: request url %s failed , http status code: %d \n", url, resp.StatusCode)
		return nil
	}
	var insResp respmodel.InstanceResp
	b, _ := ioutil.ReadAll(resp.Body)
	log.Printf("debug: response content:%s", string(b))
	err = json.Unmarshal(b, &insResp)
	if err != nil {
		log.Printf("error: unmarshal failed: %s", err.Error())
		return nil
	}
	return insResp.Hosts
}

func writeJobFile(srv model.Service, instances []respmodel.Instance) {
	jobTemplateFile := filepath.Join("conf", "template", "jobTemplate.tmpl")
	templet, err := ioutil.ReadFile(jobTemplateFile)
	if err != nil {
		log.Printf("read template %s failed, %v \n", jobTemplateFile, err)
		return
	}
	hosts := make([]string, len(instances))
	for index, insinstance := range instances {
		ipHost := fmt.Sprintf("\"%s:%d\"", insinstance.IP, insinstance.Port)
		hosts[index] = ipHost
	}
	hostsjoin := strings.Join(hosts, ", ")
	result := strings.Replace(string(templet), "$Hosts", hostsjoin, 1)
	err = ioutil.WriteFile(srv.PrometheusJobConfPath, []byte(result), os.ModePerm)
	if err != nil {
		log.Printf("generate job config file failed, file name: %s , msg: %v \n", srv.PrometheusJobConfPath, err)
		return
	}
	log.Printf("generate file %s success ,file content:\n %s \n", srv.PrometheusJobConfPath, result)
}
